import 'dart:async';

import 'package:ceramics/extensions/ab_string_extensions.dart';
import 'package:ceramics/extensions/ab_widget_extensions.dart';
import 'package:ceramics/styles/ab_styles.dart';
import 'package:ceramics/util/ab_loading.dart';
import 'package:flutter/material.dart';
import 'package:flutter_swipe_action_cell/core/cell.dart';
import 'package:get/get.dart';
import 'package:path_provider/path_provider.dart';
import 'package:record/record.dart';
import 'package:svgaplayer_flutter/player.dart';

final record = AudioRecorder();

Future<String?> showVoiceRecordOverlay() async  {
  final navigatorState =
  Navigator.of(Get.overlayContext!, rootNavigator: false);
  final overlayState = navigatorState.overlay!;
  var overlay = ABVoiceRecordOverlay();
  final overlayEntry = OverlayEntry(
    builder: (context) {
      return overlay;
    },
  );
  overlay.hide = () {
    overlayEntry.remove();
  };
  overlayState.insert(overlayEntry);
  return overlay.completer.future;
}

enum RecordState {
  waiting,
  recording,
  stop,
  cancel,
}

// ignore: must_be_immutable
class ABVoiceRecordOverlay extends StatefulWidget {
  ABVoiceRecordOverlay({super.key});
  Function? hide;
  Completer<String?> completer = Completer<String?>();
  @override
  State<ABVoiceRecordOverlay> createState() => _ABVoiceRecordOverlayState();

  Future<String?> getRecordPath() => completer.future;

}

class _ABVoiceRecordOverlayState extends State<ABVoiceRecordOverlay> {

  var _state = RecordState.waiting;
  late String _path;

  String get stateString {
    switch (_state) {
      case RecordState.waiting:
        return "";
      case RecordState.recording:
        return "Release Send";
      case RecordState.stop:
        return "Sending";
      case RecordState.cancel:
        return "Release Cancel";
    }
  }

  @override
  void initState() {
    super.initState();
    _initData();
  }

  _initData() async {
    var docDir = await getApplicationDocumentsDirectory();
    var timestamp = DateTime.now().millisecondsSinceEpoch;
    _path = "${docDir.path}/voice_$timestamp.m4a";
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {

    Widget loadingWidget = (){
      switch (_state) {
        case RecordState.waiting:
          return Transform(
              transform: Matrix4.translationValues(0, -5, 0),
              child: Image.asset('images/ceramics_40.webp',scale: 3));
        case RecordState.recording:
          return const SVGASimpleImage(assetsName: 'images/recording.svga').maxWidth(75);
        case RecordState.stop:
          return const CircularProgressIndicator();
        case RecordState.cancel:
          return const SizedBox();
      }
    }();

    ImageProvider imageProvider = _state != RecordState.cancel ? const AssetImage('images/ceramics_79.png')
      : const AssetImage('images/ceramics_81.webp');

    return Container(
      color: Colors.black.withOpacity(0.5),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          Container(
            width: 131,
            height: 84,
            decoration: BoxDecoration(
              image: DecorationImage(
                scale: 3,
                fit: BoxFit.contain,
                image: imageProvider,
              ),
            ),
            child: loadingWidget,
          ),
          const SizedBox(height: 200),
          Text(stateString, style: ABStyles.tsWhite17Bold),
          const SizedBox(height: 20),
          ClipPath(
            clipper: ArcClipper(),
            child: Material(
              child: Container(
                alignment: Alignment.topCenter,
                padding: const EdgeInsets.only(top: 18),
                height: 150,
                width: double.infinity,
                child: GestureDetector(
                  child: Column(
                    children: [
                      Image.asset(_state == RecordState.cancel ? 'images/ceramics_38.webp' : 'images/ceramics_65.webp',width: 80),
                      const SizedBox(height: 10),
                      Text('Long press to start recording.'.tr)
                    ],
                  ),
                  onTapDown: (details) {
                    _startRecord();
                    setState(() {
                      _state = RecordState.recording;
                    });
                  },
                  onPanUpdate: (details) {
                    if (details.localPosition.dy < 0) {
                      setState(() {
                        _state = RecordState.cancel;
                      });
                    } else {
                      setState(() {
                        _state = RecordState.recording;
                      });
                    }
                  },
                  onTapUp: (details) {
                    if (widget.hide != null) {
                      widget.hide!();
                    }
                    if (_state == RecordState.cancel) {
                      _cancelRecord();
                    } else {
                      _sendRecord();
                    }
                  },
                  onPanEnd: (details) {
                    if (widget.hide != null) {
                      widget.hide!();
                    }
                    if (_state == RecordState.cancel) {
                      _cancelRecord();
                    } else {
                      _sendRecord();
                    }
                  },
                )
              ),
            ),
          )
        ],
      ),
    ).onTap(() => widget.hide!());
  }

  void _startRecord() async {
    if (await record.hasPermission()) {
      await record.start(const RecordConfig(encoder: AudioEncoder.aacEld),path: _path);
    } else {
      widget.completer.complete(null);
      toast("No permission");
    }
  }

  void _cancelRecord() async {
    await record.stop();
    widget.completer.complete(null);
  }

  void _sendRecord() async {
    await record.stop();
    widget.completer.complete(_path.fileName());
  }
}

class ArcClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    final path = Path();
    var deep = 25.0;
    path.moveTo(0, deep);
    path.quadraticBezierTo(
        size.width / 2, -deep, size.width, deep);
    path.lineTo(size.width, size.height);
    path.lineTo(0, size.height);
    path.close();
    return path;
  }

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return true;
  }
}